<?php

namespace App\Services;

use App\ModelCategory;
use App\ModelClass;
use App\Lib\Util\QueryPager;

class ModelCategoryService
{
    private $leafCategories = null;

    private function baseQuery()
    {
        return ModelCategory::select('id', 'name', 'sort_order', 'parent_id');
    }

    public function getCategories(Array $input, $paging = true)
    {
        $query = $this->baseQuery();

        if (!empty($input['parentId'])) {
            $query = $query->where('parent_id', $input['parentId']);
        } else if (isset($input['parentId']) && $input['parentId'] === '0') {
            $query = $query->whereNull('parent_id');
        }

        if (!empty($input['name'])) {
            $query->where('name', 'like', '%'.$input['name'].'%');
        }

        if (!empty($input['leafIds'])) {
            $query->whereIn('id', $input['leafIds']);
        }

        $pager = new QueryPager($query);

        $pager->setRefectionMethodField('getFullPath');

        return $paging ? $pager->doPaginate($input, 'sort_order') :
            $pager->queryWithoutPaginate($input, 'sort_order');
    }

    public function getChildCategories($parentId)
    {
        if (!empty($parentId)) {
            return ModelCategory::where('parent_id', $parentId)
                ->orderBy('sort_order')->get();
        }

        return ModelCategory::whereNull('parent_id')
            ->orderBy('sort_order')->get();
    }

    public function getPossiableParentCategories($parent)
    {
        if (isset($parent)) {
            if (!empty($parent->parent_id)) {
                return ModelCategory::where('parent_id', $parent->parent_id)
                    ->orderBy('sort_order')->get();
            }
        }

        return ModelCategory::whereNull('parent_id')
            ->orderBy('sort_order')->get();
    }

    public function getChildlevelCategories($parentId)
    {
        if ($parentId == null) {
            return ModelCategory::whereNull('parent_id')
            ->orderBy('sort_order')->get();
        }
        
        return ModelCategory::where('parent_id', $parentId)
            ->orderBy('sort_order')->get();
    }

    public function getCascadeCategories($defaultCategory=null)
    {
        $allCategories = ModelCategory::select('id', 'name', 'parent_id')
            ->orderBy('sort_order')->get()->toArray();

        $allChildCategories = $this->getChildModelCategories($allCategories, $defaultCategory);

        if (isset($defaultCategory)) {
            array_push($allChildCategories, $defaultCategory);
        }

        return $allChildCategories;
    }

    public function getAllLeafCategoriesEntity()
    {
        $cates = $this->getAllLeafCategories();

        return $this->getCategories(['leafIds' => collect($cates)->pluck('id')->toArray()], false);
    }

    public function getAllLeafCategories()
    {
        $allCategories = ModelCategory::select('id', 'name', 'parent_id')
            ->orderBy('sort_order')->get()->toArray();

        $this->leafCategories = [];

        $this->getLeafCategories($allCategories, null);

        return $this->leafCategories;
    }

    private function getLeafCategories($allCategories, $parentCategory)
    {
        $children = [];

        $categoryCount = count($allCategories);

        for ($i=0; $i<$categoryCount; $i++) {
            $category = $allCategories[$i];

            if  ($parentCategory === null) {
                if (empty($category['parent_id'])) {
                    $currentCategory = $category;
                    array_push($children, $currentCategory);
                    unset($allCategories[$i]);
                }
            } else {
                if ($category['parent_id'] == $parentCategory['id']) {
                    $currentCategory = $category;
                    array_push($children, $currentCategory);
                    unset($allCategories[$i]);
                }
            }
        }

        $childrenCount = count($children);
        if ($childrenCount > 0) {
            $allCategories = array_values($allCategories);

            for ($i=0; $i<$childrenCount; $i++) {
                $currentCategory = $children[$i];

                $this->getLeafCategories($allCategories, $currentCategory);
            }
        } else {
            if ($parentCategory !== null) {
                array_push($this->leafCategories, $parentCategory);
            }
        }
    }

    public function getPossiableParentCategoriesExceptSelf($categoryId)
    {
        $categories = ModelCategory::all();
        $countCategorys = count($categories);
        for ($i=0; $i<$countCategorys; $i++) {
            if ($categories[$i]->id == $categoryId) {
                unset($categories[$i]);
                break;
            }
        }

        return $categories;
    }

    private function getChildModelCategories($allCategories, $parentCategory)
    {
        $children = [];

        $categoryCount = count($allCategories);

        for ($i=0; $i<$categoryCount; $i++) {
            $category = $allCategories[$i];

            if  ($parentCategory === null) {
                if (empty($category['parent_id'])) {
                    $currentCategory = $category;
                    array_push($children, $currentCategory);
                    unset($allCategories[$i]);
                }
            } else {
                if ($category['parent_id'] == $parentCategory['id']) {
                    $currentCategory = $category;
                    array_push($children, $currentCategory);
                    unset($allCategories[$i]);
                }
            }
        }

        $result = [];

        $childrenCount = count($children);
        if ($childrenCount > 0) {
            $allCategories = array_values($allCategories);

            for ($i=0; $i<$childrenCount; $i++) {
                $currentCategory = $children[$i];

                array_push($result, array_merge($currentCategory, [
                    'spread' => true,
                    'children' => $this->getChildModelCategories($allCategories, $currentCategory)
                ]));
            }
        }

        return $result;
    }

    public function hasChildren($categoryId)
    {
        return ModelCategory::where('parent_id', $categoryId)->count() > 0;
    }

    public function hasConstrait($categoryId)
    {
        return ModelClass::where('category_id', $categoryId)->count() > 0;
    }
}
